<?php
/**
 * DMFramework
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @url http://dmframework.nl
 */

/**
 * The error handler class is used for catching: exceptions, php errors and even fatal errors
 * (only PHP 5.3 or higher). Please disable application->debug in the configuration file when
 * you use websites for production because otherwise hackers can see valueble information of
 * your webserver.
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @package System.Core.Error
 */
class Dmf_Error_Handler
{
    /**
     * Error code
     * 
     * @var int
     */
    public $code;
    
    /**
     * Line of the error
     * 
     * @var int 
     */
    public $line;
    
    /**
     * File where the error happend
     * 
     * @var string 
     */
    public $file;
    
    /**
     * The name of the exception
     * 
     * @var string 
     */
    public $exceptionName;
    
    /**
     * The stack trace
     * 
     * @var array
     */
    public $stackTrace = array();
    
    /**
     * The error message
     * 
     * @var string 
     */
    public $message;
    
    /**
     * The error exception
     *  
     * @var Exception
     */
    public $exception;
    
    /**
     * The error handler
     * 
     * @var Dmf_Error_Handler|null
     */
    private static $_error;
    
    /**
     * Get the last error instance
     *  
     * @return Dmf_Error_Handler
     */
    public static function getLastInstance()
    {
        return self::$_error;
    }
    
    /**
     * Constructor
     * 
     * @param Exception|Dmf_Exception_Error $error 
     */
    public function __construct( $error )
    {
        $this->code = $error->getCode();
        $this->line = $error->getLine();
        $this->file = $error->getFile();
        
        $this->stackTrace = $error->getTrace();
        $this->message = $error->getMessage();
        
        if ( strstr( $error->getFile(), 'system' . DIRECTORY_SEPARATOR . 'cache' ) )
        {
            $error = new Dmf_Exception_Parser;
        }
        
        $parts = explode( '_', get_class( $error ) );
        $this->exception = $error;
        $this->exceptionName = end( $parts );
    }
    
    /**
     * Display the error to the user 
     */
    public function display()
    {
        //ERROR MOD
        Dmf_Mail::create()->setSubject( 'CMS error' )
            -> addSender( 'dillen@t2i.nl' )
            -> setContent( $this->message . ' in file ' . $this->file . ' on line ' . $this->line )
            -> send();
        
        return true;
        //END ERROR MOD
        
        @ob_clean();
        
        if ( file_exists( 'application/controllers/ErrorController.php' ) && file_exists( 'application/views/Error/index.phtml' ) && self::$_error == null && $this->code != E_ERROR )
        {
            self::$_error = $this;
            $router = new Dmf_Router();
            $router->dispatch( Dmf_Request::fromRoute( 'Error', 'index' ) );
            
            exit;
        }
        
        @ob_clean();
        
        $view = new Dmf_Error_View( $this );
        $view->render();
        
        exit;
    }
    
    /**
     * Catch fatal errors
     * 
     * @return null 
     */
    public static function shutdown()
    {
        $error = error_get_last();
        
        chdir( Dmf_Application::getInstance()->getConfig()->asObject()->application->path );
        
        if ( ! isset( $error['type'] ) || strlen( $error['type'] ) == 0 ) return;
        
        self::handlePhp( E_ERROR, $error['message'], $error['file'], $error['line'], array() );
    }
    
    /**
     * Handle exceptions
     * 
     * @param Exception $exception 
     */
    public static function handle( $exception )
    {
        $error = new Dmf_Error_Handler( $exception );
        $error->display();
    }
    
    /**
     * Handle regular PHP errors.
     * 
     * @param int $code
     * @param string $message
     * @param string $file
     * @param int $line
     * @param string $context
     * @return null
     */
    public static function handlePhp( $code, $message, $file, $line, $context )
    {
        if ( ! ( error_reporting() & $code ) ) 
        {
            return;
        }
        
        $error = new Dmf_Error_Handler( new Dmf_Exception_Error( array(
            'code' => $code,
            'message' => $message,
            'file' => $file,
            'line' => $line,
            'context' => $context
        ) ) );
        
        $error->display();
    }
}